package com.bzkj.web.controller.system;

import com.bzkj.common.constant.Constants;
import com.bzkj.common.core.domain.AjaxResult;
import com.bzkj.common.core.domain.entity.SysDept;
import com.bzkj.common.core.domain.entity.SysMenu;
import com.bzkj.common.core.domain.entity.SysRole;
import com.bzkj.common.core.domain.entity.SysUser;
import com.bzkj.common.core.domain.model.LoginBody;
import com.bzkj.common.core.redis.RedisCache;
import com.bzkj.common.utils.SecurityUtils;
import com.bzkj.common.utils.uuid.IdUtils;
import com.bzkj.framework.web.service.SysLoginService;
import com.bzkj.framework.web.service.SysPermissionService;
import com.bzkj.quartz.domain.SysJob;
import com.bzkj.quartz.service.ISysJobService;
import com.bzkj.system.service.ISysConfigService;
import com.bzkj.system.service.ISysMenuService;
import com.bzkj.system.service.ISysUserService;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 登录验证
 *
 * @author ruoyi
 */
@RestController
public class SysLoginController {
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private ISysUserService userService;

    @Resource
    private ISysConfigService configService;

    @Resource
    private RedisCache redisCache;

    @Resource
    private ISysJobService jobService;

    private static final String MULTIPLE_USERS_MSG = "存在多个同名用户，请使用工号登录！";
    private static final String USER_NOT_FOUND_MSG = "用户不存在/密码错误";
    private static final String NCC_USER_NOT_FOUND_MSG = "NCC无此用户信息！";
    private static final String SUCCESS_KEY = "success";
    private static final String DEPT_NAME_KEY = "deptName";
    private static final String ROLES_KEY = "roles";
    private static final String DEPT_ID_KEY = "deptId";
    private static final String USER_ID_KEY = "userId";
    private static final String WAREHOUSE_IDS = "warehouseIds";
    private static final String PDA_ROLE_KEY = "pda_role";
    private static final int ERROR_CODE = 500;

    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) throws SchedulerException {
        AjaxResult ajax = AjaxResult.success();
        // 创建一个Pattern对象，用于判断登录账号是否为工号
        String nikeName = null;

        boolean matches = loginBody.getUsername().matches("^[a-zA-Z0-9].*");

        // 如果不是用的工号登录，则根据姓名查询工号
        if (!matches) {
            nikeName = loginService.selectUserNameByNickName(loginBody.getUsername());
            if (Objects.equals(nikeName, MULTIPLE_USERS_MSG)) {
                return AjaxResult.error(MULTIPLE_USERS_MSG);
            } else if (Objects.equals(nikeName, USER_NOT_FOUND_MSG)) {
                return AjaxResult.error(USER_NOT_FOUND_MSG);
            }
        }
        // 生成令牌
        String token = loginService.login(matches ? loginBody.getUsername() : nikeName, loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid(), loginBody.getType());

        ajax.put(Constants.TOKEN, token);

        if ("true".equals(configService.selectConfigByKey("change.password.periodically"))) {
            Map<String, Integer> pwdExpire = loginService.isPwdExpire(matches ? loginBody.getUsername() : nikeName);
            if (pwdExpire.get("flag") == 1) {
                ajax.put("res_code", 1001);
                String signKey = Constants.RESET_SIGN_KEY + (matches ? loginBody.getUsername() : nikeName);
                String signCode = IdUtils.fastSimpleUUID();
                redisCache.setCacheObject(signKey, signCode, Constants.RESET_EXPIRATION, TimeUnit.MINUTES);
                ajax.put("reset_sign", signCode);
            }
            ajax.put("days", pwdExpire.get("days"));
        }
        // 登录成功后执行定时任务
//        executeJobService();
        return ajax;
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    /**
     * PDA登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login/PDA")
    public AjaxResult pdaLogin(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        String username = loginBody.getUsername();

        // 判断是否使用工号登陆
        String workNo = getWorkNo(username);
        if (workNo == null) {
            return buildErrorResponse(ajax, MULTIPLE_USERS_MSG);
        }

        // 生成令牌
        String token = loginService.login(workNo, loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid(), loginBody.getType());
        if (USER_NOT_FOUND_MSG.equals(token)) {
            return buildErrorResponse(ajax, USER_NOT_FOUND_MSG);
        } else if (token.startsWith("密码输入错误")) {
            return buildErrorResponse(ajax, token);
        }

        SysUser sysUser = userService.selectUserByUserName(workNo);
        if (sysUser != null) {
            return buildSuccessResponse(ajax, sysUser);
        }

        return ajax;
    }

    /**
     * 根据姓名查询工号
     *
     * @param username 姓名
     * @return 工号
     */
    private String getWorkNo(String username) {
        String rex = "^[a-zA-Z0-9].*";
        if (username.matches(rex)) {
            return username;
        }
        String workNo = loginService.selectUserNameByNickName(username);
        return MULTIPLE_USERS_MSG.equals(workNo) ? null : workNo;
    }

    /**
     * 构建错误返回体
     *
     * @param ajax    返回体
     * @param message 返回消息
     * @return 返回体
     */
    private AjaxResult buildErrorResponse(AjaxResult ajax, String message) {
        ajax.put(SUCCESS_KEY, false);
        ajax.put("message", message);
        ajax.put("code", ERROR_CODE);
        return ajax;
    }

    /**
     * 构建成功返回体
     *
     * @param ajax    返回体
     * @param sysUser 登录用户
     * @return 返回体
     */
    private AjaxResult buildSuccessResponse(AjaxResult ajax, SysUser sysUser) {
        SysDept dept = sysUser.getDept();
        Long userId = sysUser.getUserId();
        Long deptId = dept.getDeptId();
        String deptName = dept.getDeptName();


        HashMap<String, Object> resultMap = userService.selectPdaDetail(sysUser.getUserName());
        if (resultMap == null) {
            return buildErrorResponse(ajax, NCC_USER_NOT_FOUND_MSG);
        }

        // 组合用户的角色信息
        List<SysRole> roles = sysUser.getRoles();
        ArrayList<String> pdaRole = new ArrayList<>();
        ArrayList<HashMap<String, String>> roleList = new ArrayList<>();
        for (SysRole role : roles) {
            HashMap<String, String> rolesMap = new HashMap<>(2);
            rolesMap.put("name", role.getRoleName());
            rolesMap.put("id", role.getRoleId().toString());
            roleList.add(rolesMap);
            if (role.getPda() != null && !role.getPda().isEmpty()){
                pdaRole.addAll(Arrays.asList(role.getPda().split(",")));
            }
        }
        //用户的仓库数据
        ArrayList<HashMap<String, String>> warehouseList = new ArrayList<>();
        if (resultMap.get("warehouse_ids") != null) {
            List<String> list = Arrays.asList(resultMap.get("warehouse_ids").toString().split(","));
            for (String str : list) {
                String[] parts = str.replaceAll("\\s+:\\s+", ":").split(":");
                HashMap<String, String> warehouseMap = new HashMap<>(2);
                warehouseMap.put("id", parts[0].trim());
                warehouseMap.put("name", parts[1].trim());
                warehouseList.add(warehouseMap);
            }
            resultMap.put(WAREHOUSE_IDS, warehouseList);
        } else {
            resultMap.put(WAREHOUSE_IDS, new ArrayList<>());
        }
        resultMap.put(ROLES_KEY, roleList);
        resultMap.put(PDA_ROLE_KEY, pdaRole);
        resultMap.put(DEPT_ID_KEY, deptId.toString());
        resultMap.put(USER_ID_KEY, userId.toString());
        resultMap.remove("warehouse_ids");
        resultMap.put(DEPT_NAME_KEY, deptName);
        ajax.put("data", resultMap);
        ajax.put(SUCCESS_KEY, true);
        return ajax;
    }

    /**
     * 登录成功后执行定时任务
     */
    @Async
    protected void executeJobService() throws SchedulerException {
        SysJob sysJob = new SysJob();
        sysJob.setStatus("0");
        sysJob.setJobGroup("NCC");
        List<SysJob> sysJobs = jobService.selectJobList(sysJob);
        for (SysJob job : sysJobs) {
            String invokeTarget = job.getInvokeTarget();
            if (invokeTarget.endsWith("(true)")) {
                job.setInvokeTarget(invokeTarget.replace("(true)", "(false)"));
            }
            jobService.run(job);
        }
    }

}
